home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / tex / archives / dvidvi1_0.lha / DviDvi / dvidvi.c < prev    next >
C/C++ Source or Header  |  1993-07-28  |  33KB  |  1,295 lines

  1. /*
  2.  *   This program converts dvi files to dvi files;
  3.  *   the command line options are:
  4.  *
  5.  *    page n is first page selected          -f n
  6.  *    page n is last page selected          -l n
  7.  *    print at most n pages              -n n
  8.  *    include pages (ranges allowed)        -i { n1..n2 | n1 }[,...]
  9.  *    exclude pages (ranges allowed)        -x { n1..n2 | n1 }[,...]
  10.  *    work in quiet mode              -q
  11.  *    reverse pages                  -r
  12.  *    select even                  -m 2:1
  13.  *    select odd                  -m 2:0
  14.  *    print both on same page           -m 2:0,1(5.5in,0in)
  15.  *    do folded brochures              -m 4:-3,0(5.5in,0in)
  16.  *                          -m 4:1,-2(5.5in,0in)
  17.  *    etc.
  18.  *
  19.  *    scale magnification              -sm m
  20.  *    scale document-width              -sw m
  21.  *    scale document-height              -sh m
  22.  *
  23.  *    The arguments m are instances of magsteps. For example -sm 2
  24.  *    multiplies the document-magnification by magstep(2) (1.44) and
  25.  *    -sw -2 multiplies the document-with by magstep(2) (0.694).
  26.  *
  27.  *    The original program is by Tomas Rokicki (version 0.5) but it was
  28.  *    modified and improved by Esteban ZIMANYI ezimanyi@rc1.vub.ac.be
  29.  *    to give version 1.0.
  30.  *
  31.  *    This version has been tested for the IBM PC and compatibles under
  32.  *    compilers Turbo C 2.0 and Microsoft C 6.0.
  33.  *
  34.  *    The options -sm, -sw and -sh were added by Jochen Wiedmann to support
  35.  *    PasTeX on the Amiga. This was needed because PasTeX doesn't ignore
  36.  *    the Width- and Height-Parameters included in the Postamble. PasTeX
  37.  *    needs them to be rearranged to work fine.
  38.  *
  39.  */
  40. #define SEEK_SET 0
  41. #define SEEK_CUR 1
  42. #define SEEK_END 2
  43.  
  44. #define BANNER "\nThis is dvidvi 1.0, Copyright (C) 1988-91, Radical Eye Software\n"
  45. #define STRINGSIZE (500)  /* maximum number of strings in program */
  46.  
  47. #ifndef VMS
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <math.h>
  51. #else /* VMS */
  52. #include "sys$library:stdio.h"       /* AKT: added sys$library: */
  53. #include <alloc.h>
  54. #endif /* VMS */
  55. #define MAXPPERP (32)
  56.  
  57. /* defines READBIN, WRITEBIN, PATHSEP and DIRSEP*/
  58.  
  59. #ifdef MSDOS
  60. #define READBIN     "rb"    /* MSDOS must use binary mode */
  61. #define WRITEBIN    "wb"
  62. #define PATHSEP     ';'
  63. #define DIRSEP        '\\'
  64. #else
  65. #ifdef VMS
  66. #define READBIN     "rb"    /* VMS must use binary mode */
  67. #define WRITEBIN    "wb"
  68. #define PATHSEP     ','
  69. #define DIRSEP        ':'
  70. #else
  71. #define READBIN     "r"     /* UNIX doesn't care */
  72. #define WRITEBIN    "w"
  73. #define PATHSEP     ':'
  74. #define DIRSEP        '/'
  75. #endif
  76. #endif
  77.  
  78. #ifdef XENIX
  79. #define SHORTINT
  80. #else
  81. #undef SHORTINT
  82. #endif
  83. #ifdef MSDOS
  84. #define SHORTINT
  85. #endif
  86.  
  87. /*
  88.  *   Type declarations.  integer must be a 32-bit signed; shalfword must
  89.  *   be a sixteen-bit signed; halfword must be a sixteen-bit unsigned;
  90.  *   quarterword must be an eight-bit unsigned.
  91.  */
  92. typedef long integer;
  93. typedef char boolean;
  94. typedef short shalfword ;
  95. typedef unsigned long longword;
  96. typedef unsigned short halfword ;
  97. typedef unsigned char quarterword ;
  98. typedef short Boolean ;
  99.  
  100. /*
  101.  *   Some globals to keep everyone happy.
  102.  */
  103. integer numpages ;    /* the total number of pages in the dvi file. */
  104. integer TeXfonts[256] ; /* information about each font */
  105. char fontseen[256] ; /* have we defined this font yet? */
  106. int modulo ;         /* our mod value */
  107. struct pagespec {
  108.    int pageno, reversed ;
  109.    long hoffset, voffset ; /* in scaled points */
  110. } pages[MAXPPERP] ;  /* the organization of the pages on output */
  111. int pagesperpage ;   /* how many pages crammed onto each page? */
  112. FILE *infile ;         /* input dvi file (cannot be a stream) */
  113. FILE *outfile ;      /* output dvi file */
  114.  
  115. char *temp ;    /* a temporary place to put things */
  116. char *nextstring, *maxstring ;
  117. char *oname ;              /* output dvi file name */
  118. char *iname ;              /* input dvi file name */
  119. char *strings ;           /* pointer of the string pool */
  120.  
  121. char banner[] = BANNER ;      /* the startup message */
  122. integer inlength ;    /* the length of the input dvi file */
  123. integer postloc ;    /* location of the postamble */
  124. integer mag ;        /* magnification factor */
  125. integer pagecount ;    /* number of actual pages */
  126. integer landscape = 0;       /* if landscape special, here it is! */
  127. int rem0special ;    /* should we remove the first first-page special? */
  128. integer prevpp = -1 ;       /* previous page pointer on output */
  129. integer outputpages ;    /* number of pages output */
  130. integer dviloc ;    /* our position in the output file */
  131. integer pagefake ;    /* number of pages, rounded up to multiple of modulo */
  132.  
  133. Boolean firsttransf = 0, lasttransf = 0;
  134. integer firstpage ;    /* first page selected (option -p) */
  135. integer lastpage ;    /* last page selected (option -l) */
  136. integer maxpages ;    /* maximum number of page selected (option -n) */
  137. short quiet ;          /* quiet mode (option -q) */
  138. Boolean exctransf[40][2] ; /* if the ranges of pages to exclude (option -x)
  139.                 have to be transformed */
  140. integer exclude[40][2] ; /* the ranges of pages to exclude (option -x)
  141.              It is supposed that there are at most 40 ranges
  142.              to exclude in the command line */
  143. short excludeseq ;     /* number of ranges to exclude (option -x) */
  144. Boolean inctransf[40][2] ; /* if the ranges of pages to exclude (option -x)
  145.                 have to be transformed */
  146. integer include[40][2] ; /* the ranges of pages to include (option -i)
  147.              It is supposed that there are at most 40 ranges
  148.              to include in the command line */
  149. short includeseq ;     /* number of ranges to include (option -i) */
  150. integer *pageloc ;
  151. integer *pagenumbers ;
  152. int prettycolumn ;     /* the column we are at when running pretty */
  153.  
  154.  
  155. /*  Added 28.07.1993,    Jochen Wiedmann     */
  156. double scale_magstep = 0.0;
  157. double scale_width = 0.0;
  158. double scale_height = 0.0;
  159. /*                        */
  160.  
  161.  
  162. /*
  163.  *   This array holds values that indicate the length of a command, if
  164.  *   we aren't concerned with that command (which is most of them) or
  165.  *   zero, if it is a special case.  This makes running through the
  166.  *   dvi file a lot easier (and probably faster) than any form of
  167.  *   dispatch table, especially since we really don't care what the
  168.  *   pages are made of.
  169.  */
  170. short comlen[256] = {
  171.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0-15 */
  172.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 16-31 */
  173.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 32-47 */
  174.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 48-63 */
  175.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 64-79 */
  176.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80-95 */
  177.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 96-111 */
  178.    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 112-127 */
  179.    2, 3, 4, 5, 9, 2, 3, 4, 5, 9, 1, 0, 0, 1, 1, 2, /* 128-143 */
  180.    3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 2, 3, 4, /* 144-159 */
  181.    5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, /* 160-175 */
  182.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 176-191 */
  183.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 192-207 */
  184.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 208-223 */
  185.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 0, /* 224-239 */
  186.    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };/* 240-255 */
  187.  
  188. /*
  189.  *   Input bytes from the dvi file.
  190.  *   These routines could probably be sped up significantly; but they are
  191.  *   very machine dependent, so I will leave such tuning to the installer.
  192.  *   They simply get and return bytes in batches of one, two, three, and four,
  193.  *   updating the current position as necessary.
  194.  */
  195.  
  196. void
  197. abortpage()
  198. {
  199.    error("! unexpected eof on DVI file") ;
  200. }
  201.  
  202. shalfword dvibyte()
  203. {
  204.   register shalfword i ;
  205.   if ((i=getc(infile))==EOF)
  206.     abortpage() ;
  207.   return(i) ;
  208. }
  209.  
  210. halfword  twobytes()
  211. {
  212.   register halfword i ;
  213.   i = dvibyte() ;
  214.   return(i*256+dvibyte()) ; }
  215.  
  216. integer   threebytes()
  217. {
  218.   register integer i ;
  219.   i = twobytes() ;
  220.   return(i*256+dvibyte()) ; }
  221.  
  222. longword  fourbytes()
  223. {
  224.   register longword i;
  225.   i = twobytes();
  226.   return((i<<16)+twobytes());
  227. }
  228.  
  229. shalfword
  230. signedbyte()
  231. {
  232.   register shalfword i ;
  233.   if ((i=getc(infile))==EOF)
  234.     abortpage() ;
  235.   if (i<128) return(i) ;
  236.   else return(i-256) ;
  237. }
  238.  
  239. shalfword
  240. signedpair()
  241. {
  242.   register shalfword i ;
  243.   i = signedbyte() ;
  244.   return(i*256+dvibyte()) ;
  245. }
  246.  
  247. integer
  248. signedtrio()
  249. {
  250.   register integer i ;
  251.   i = signedpair() ;
  252.   return(i*256+dvibyte()) ;
  253. }
  254.  
  255. integer
  256. signedquad()
  257. {
  258.   register integer i ;
  259.   i = signedpair() ;
  260.   return(i*65536+twobytes()) ;
  261. }
  262.  
  263. /*
  264.  * Routines for the transformation of the pages specified with
  265.  * the @ parameter into the actual number of page from the file
  266.  *
  267.  * trans(p,q) looks for the q'th occurrence of the page numbered p
  268.  * transformpages makes the transformation for the options -f -i -l -x
  269.  */
  270.  
  271. integer transf(p,q)
  272. integer p;
  273. halfword q;
  274. {
  275. int i=0, j=0;
  276.  
  277.    while( j != q && i < pagecount )
  278.       if ( pagenumbers[i++] == p ) j++;
  279.    if ( j != q ) error ("! Page specified not found");
  280.    return (i++);
  281. }
  282. void transformpages()
  283. {
  284. int i;
  285.  
  286.    if (firsttransf) firstpage=transf(firstpage,firsttransf);
  287.    if (lasttransf) lastpage=transf(lastpage,lasttransf);
  288.    for ( i= 0; i< 40; i++) {
  289.       if (exctransf[i][0]) exclude[i][0]=transf(exclude[i][0],exctransf[i][0]);
  290.       if (exctransf[i][1]) exclude[i][1]=transf(exclude[i][1],exctransf[i][1]);
  291.       if (inctransf[i][0]) include[i][0]=transf(include[i][0],inctransf[i][0]);
  292.       if (inctransf[i][1]) include[i][1]=transf(include[i][1],inctransf[i][1]);
  293.       }
  294. }
  295. /*
  296.  *
  297.  */
  298. integer fontdeflen(p)
  299. integer p;
  300. {
  301.    fseek(infile,p+14,SEEK_SET);
  302.    return (16L+dvibyte()+dvibyte());
  303. }
  304.  
  305. /*
  306.  *     Simulation of dvibuf, get the character located at the position
  307.  *     p in the input dvi file
  308.  */
  309. unsigned char dvibuf(p)
  310. integer p;
  311. {
  312.   fseek(infile,p,SEEK_SET);
  313.   return(dvibyte());
  314. }
  315.  
  316. /*
  317.  *     Read a string of length n from the file into the string temp
  318.  */
  319. void stringdvibuf(p,n)
  320. integer p,n;
  321. {
  322.   fseek(infile,p,SEEK_SET);
  323.   while ( n-- > 0 )
  324.     *temp++ = dvibyte();
  325. }
  326.  
  327. /*
  328.  *   Print a usage error messsage, and quit.
  329.  */
  330. usage() {
  331.    (void)fprintf(stderr,banner);
  332.    (void)fprintf(stderr,"Usage:  dvidvi [options] input[.dvi] [output]\n");
  333.    (void)fprintf(stderr,"where options are:\n");
  334.    (void)fprintf(stderr,"    [-f n] first page printed     [-l n] last page printed\n");
  335.    (void)fprintf(stderr,"    [-n n] print at most n pages  \n");
  336.    (void)fprintf(stderr,"    [-i {n1..n2 | n3}[,...]] include pages\n");
  337.    (void)fprintf(stderr,"    [-x {n1..n2 | n3}[,...]] exclude pages\n");
  338.    (void)fprintf(stderr,"    [-q] quiet mode               [-r] reverse pages\n");
  339.  
  340.  
  341. /*  Added 28.07.1993,    Jochen Wiedmann     */
  342.    (void)fprintf(stderr,"    [-sm m] scale magnification by magstep(m)\n");
  343.    (void)fprintf(stderr,"    [-sw m] scale width by magstep(m)\n");
  344.    (void)fprintf(stderr,"    [-sh m] scale height by magstep(m)\n");
  345. /*                        */
  346.  
  347.  
  348.    (void)fprintf(stderr,"    [-m modulo:pagespecs]\n");
  349. #ifndef VMS
  350.    exit(1) ;
  351. #else /* VMS */
  352.    exit(0x10000002) ;
  353.    /* AKT: was exit(1) */
  354. #endif /* VMS */
  355. }
  356. /*
  357.  *   Print an error message, and exit if it is fatal.
  358.  */
  359. error(s)
  360. char *s ;
  361. {
  362.    (void)fprintf(stderr, "%s\n", s) ;    /* AKT: was dvidvi: %s */
  363.    if (*s == '!')
  364. #ifndef VMS
  365.       exit(1) ;
  366. #else /* VMS */
  367.       exit(0x10000002) ;
  368.       /* AKT: was exit(1) */
  369. #endif /* VMS */
  370. }
  371. /*
  372.  *   This function calculates approximately (whole + num/den) * sf.
  373.  *   No need for real extreme accuracy; one ten thousandth of an
  374.  *   inch should be sufficient.
  375.  *
  376.  *   No `sf' parameter means to use an old one; inches are assumed
  377.  *   originally.
  378.  *
  379.  *   Assumptions:
  380.  *
  381.  *    0 <= num < den <= 10000
  382.  *    0 <= whole
  383.  */
  384. integer defaultscale = 4736286 ;
  385. integer scale(whole, num, den, sf)
  386. integer whole, num, den, sf ;
  387. {
  388.    integer v ;
  389.  
  390.    if (sf)
  391.       defaultscale = sf ;
  392.    else
  393.       sf = defaultscale ;
  394.    v = whole * sf + num * (sf / den) ;
  395.    if (v / sf != whole || v < 0 || v > 0x40000000L)
  396.       error("! arithmetic overflow in parameter") ;
  397.    sf = sf % den ;
  398.    v += (sf * num * 2 + den) / (2 * den) ;
  399.    return(v) ;
  400. }
  401. /*
  402.  *   Multiplies *p by 1000 and divides it by mag.  Avoiding overflow.
  403.  *
  404.  *   1 <= mag <= 1000000 ;
  405.  *   0 <= *p <= 2^30
  406.  *
  407.  *   (Could blow up if a parameter * mag / 1000 > 2^30 sp.)
  408.  */
  409. scalemag(p)
  410. long *p ;
  411. {
  412.    int negative ;
  413.  
  414.    negative = 0 ;
  415.    if (*p < 0) {
  416.       negative = 1 ;
  417.       *p = - *p ;
  418.    }
  419.    *p = 1000 * (*p / mag) + (2000 * (*p % mag) + mag) / (2 * mag) ;
  420.    if (negative)
  421.       *p = - *p ;
  422. }
  423. /*
  424.  *   Convert a sequence of digits into an integer; return -1 if no digits.
  425.  *   Advance the passed pointer as well.
  426.  */
  427. integer myatol(s)
  428. char **s ;
  429. {
  430.    register char *p ;
  431.    register integer result ;
  432.  
  433.    result = 0 ;
  434.    p = *s ;
  435.    while ('0' <= *p && *p <= '9') {
  436.       if (result > 100000000)
  437.      error("! arithmetic overflow in parameter") ;
  438.       result = 10 * result + *p++ - '0' ;
  439.    }
  440.    if (p == *s)
  441.       usage() ;
  442.    else {
  443.       *s = p ;
  444.       return(result) ;
  445.    }
  446. }
  447. /*
  448.  *   Get a dimension, allowing all the various extensions, and
  449.  *   defaults.
  450.  */
  451. integer myatodim(s)
  452. char **s ;
  453. {
  454.    register integer w, num, den ;
  455.    register char *p ;
  456.    int negative = 0 ;
  457.  
  458.    p = *s ;
  459.    if (**s == '-') {
  460.       (*s)++ ;
  461.       negative = 1 ;
  462.    }
  463.    w = myatol(s) ;
  464.    if (w < 0)
  465.       usage() ;
  466.    p = *s ;
  467.    num = 0 ;
  468.    den = 1 ;
  469.    if (*p == '.') {
  470.       p++ ;
  471.       while ('0' <= *p && *p <= '9') {
  472.      if (den < 1000) {
  473.         den *= 10 ;
  474.         num = num * 10 + *p - '0' ;
  475.      }
  476.      p++ ;
  477.       }
  478.    }
  479. /*
  480.  *   Allowed units are `in', `cm', `mm', `pt', `sp', `cc', `dd', and `pc';
  481.  *   must be in lower case.
  482.  */
  483.    if (*p == 'c' && p[1] == 'm') {
  484. /*  centimeters need to be multiplied by 72.27 * 2^16 / 2.54, or 1 864 680 */
  485.       w = scale(w, num, den, 1864680L) ;
  486.    } else if (*p == 'p' && p[1] == 't') {
  487. /*  real points need to be multiplied by 2^16 */
  488.       w = scale(w, num, den, 65536L) ;
  489.    } else if (*p == 'p' && p[1] == 'c') {
  490. /*  picas need to be multiplied by 65536 * 12, or 786 432 */
  491.       w = scale(w, num, den, 786432L) ;
  492.    } else if (*p == 'm' && p[1] == 'm') {
  493. /*  millimeters need to be multiplied by 72.27 * 2^16 / 25.4, or 186 468 */
  494.       w = scale(w, num, den, 186468L) ;
  495.    } else if (*p == 's' && p[1] == 'p') {
  496. /*  scaled points are already taken care of; simply round */
  497.       w = scale(w, num, den, 1L) ;
  498.    } else if (*p == 'b' && p[1] == 'p') {
  499. /*  big points need to be multiplied by 72.27 * 65536 / 72, or 65782 */
  500.       w = scale(w, num, den, 65782L) ;
  501.    } else if (*p == 'd' && p[1] == 'd') {
  502. /*  didot points need to be multiplied by 65536 * 1238 / 1157, or 70124 */
  503.       w = scale(w, num, den, 70124L) ;
  504.    } else if (*p == 'c' && p[1] == 'c') {
  505. /*  cicero need to be multiplied by 65536 * 1238 / 1157 * 12, or 841 489 */
  506.       w = scale(w, num, den, 841489L) ;
  507.    } else if (*p == 'i' && p[1] == 'n') {
  508. /*  inches need to be multiplied by 72.27 * 65536, or 4 736 286 */
  509.       w = scale(w, num, den, 4736286L) ;
  510.    } else {
  511. /*  use default values */
  512.       w = scale(w, num, den, 0L) ;
  513.       p -= 2 ;
  514.    }
  515.    p += 2 ;
  516.    *s = p ;
  517.    return(negative?-w:w) ;
  518. }
  519. /*
  520.  * This function determine if the page has to be printed
  521.  * depending on the values of options -f, -l, -i and -x
  522.  */
  523.  
  524. short selectedpage (n)
  525. integer n;
  526. {
  527. short i;
  528.  
  529.    if ( firstpage > n || n > lastpage ) return(0);
  530.    for ( i=0 ; i < excludeseq ; i++ )
  531.       if ( exclude[i][0] <= n && n <= exclude[i][1] )
  532.      return(0);
  533.    if (includeseq == 0) return (1);
  534.    for ( i=0 ; i < includeseq ; i++ )
  535.       if ( include[i][0] <= n && n <= include[i][1] )
  536.      return(1);
  537.    return(0);
  538. }
  539.  
  540. /*
  541.  *   Initialize sets up all the globals and data structures.
  542.  */
  543. void
  544. initialize()
  545. {
  546. int i;
  547. /* initialize values in case of option -m is not specified */
  548.    modulo = 1 ;
  549.    pages[0].hoffset = 0 ;
  550.    pages[0].voffset = 0 ;
  551.    pages[0].pageno = 0 ;
  552.    pages[0].reversed = 0 ;
  553.    pagesperpage = 1 ;
  554.    for ( i= 0; i< 40; i++) {
  555.     exctransf[i][0] = exctransf[i][1] = 0;
  556.     inctransf[i][0] = inctransf[i][1] = 0;
  557.     }
  558.    firsttransf = lasttransf = 0;
  559.  
  560.    excludeseq = 0;
  561.    includeseq = 0;
  562.    firstpage = 1;
  563.    lastpage = 1000000;
  564.    maxpages = 1000000;
  565.    quiet = 0;
  566.    strings =(char *) malloc(STRINGSIZE) ;
  567.    if (strings == 0)
  568.       error("! no memory for strings") ;
  569.    maxpages = 100000 ;
  570.    nextstring = strings ;
  571.    iname = strings ;
  572.    *nextstring++ = 0 ;
  573.     maxstring = strings + STRINGSIZE - 200;
  574. }
  575.  
  576. /*
  577.  *   Parse the arguments to the routine, and stuff everything away
  578.  *   into those globals above.
  579.  */
  580. processargs(argc, argv)
  581. int argc ;
  582. char *argv[] ;
  583. {
  584.    char *q ;
  585.    int i, pageno, lastext = -1 ;
  586.    long hoffset, voffset ;
  587.    int reversed ;
  588.  
  589.    initialize ();
  590.    if (argc < 2 || argc > 14)
  591.       usage() ;
  592.  
  593. /*
  594.  *   This next whole big section of code is straightforward; we just scan
  595.  *   the options.  An argument can either immediately follow its option letter
  596.  *   or be separated by spaces.  Any argument not preceded by '-' and an
  597.  *   option letter is considered a file name.
  598.  */
  599.    for (i=1; i<argc; i++) {
  600.       if (*argv[i]=='-') {
  601.      char *p=argv[i]+2 ;
  602.      char c=argv[i][1] ;
  603.      switch (c) {
  604. case 'f' :
  605.         if (*p == 0 && argv[i+1])
  606.            p = argv[++i] ;
  607.         if (*p == '(' && *(p+1) == '@' ) {
  608.            p+=2; firsttransf = myatol(&p); p++;
  609.            }
  610.         else if (*p == '@') {
  611.            p++; firsttransf = 1 ;
  612.            }
  613. #ifdef SHORTINT
  614.         if(sscanf(p, "%d", &firstpage)==0)
  615. #else    /* ~SHORTINT */
  616.         if(sscanf(p, "%ld", &firstpage)==0)
  617. #endif    /* ~SHORTINT */
  618.            error("! Bad first page option (-f).") ;
  619.         break ;
  620. case 'i' :
  621.         if (*p == 0 && argv[i+1])
  622.            p = argv[++i] ;
  623.         while (*p != 0) {
  624.            if (*p == '(' && *(p+1) == '@' ) {
  625.           p+=2; inctransf[includeseq][0] = myatol(&p); p++;
  626.           }
  627.            else if (*p == '@') {
  628.           p++; inctransf[includeseq][0] = 1 ;
  629.           }
  630.            include[includeseq][0]=myatol(&p);
  631.            if (*p == '.' && *(p+1) == '.' ) {
  632.           p += 2;
  633.           if (*p == '(' && *(p+1) == '@' ) {
  634.              p+=2; inctransf[includeseq][1] = myatol(&p); p++;
  635.              }
  636.           else if (*p == '@') {
  637.              p++; inctransf[includeseq][1] = 1 ;
  638.              }
  639.           include[includeseq][1] = myatol(&p);
  640.            }
  641.            else {
  642.           include[includeseq][1] = include[includeseq][0];
  643.           inctransf[includeseq][0] = inctransf[includeseq][1] ;
  644.           }
  645.            includeseq++ ;
  646.            if (*p != ',' && *p !=0 )
  647.           error("! Bad page range option (-i).") ;
  648.            if (*p == ',' )
  649.             p++ ;
  650.         } /* while */
  651.         break ;
  652. case 'l':
  653.         if (*p == 0 && argv[i+1])
  654.            p = argv[++i] ;
  655.         if (*p == '(' && *(p+1) == '@' ) {
  656.            p+=2; lasttransf = myatol(&p); p++;
  657.            }
  658.         else if (*p == '@') {
  659.            p++; lasttransf = 1 ;
  660.            }
  661. #ifdef SHORTINT
  662.         if(sscanf(p, "%ld", &lastpage)==0)
  663. #else    /* ~SHORTINT */
  664.         if(sscanf(p, "%d", &lastpage)==0)
  665. #endif    /* ~SHORTINT */
  666.            error("! Bad last page option (-l).") ;
  667.         break ;
  668. case 'm' :
  669.         if (*p == 0 && argv[i+1])
  670.            p = argv[++i] ;
  671. /*
  672.  *   Is there a modulo supplied?  Grab it if so; otherwise default to 1.
  673.  */
  674.        for (q=p; *q != 0; q++)
  675.           if (*q == ':')
  676.          break ;
  677.        if (*q == ':') {
  678.           modulo = myatol(&p) ;
  679.           if (*p != ':')
  680.          usage() ;
  681.           if (modulo < 1 || modulo > MAXPPERP)
  682.          error("! modulo must lie between 1 and 32") ;
  683.           p++ ;
  684.        }
  685. /*
  686.  *   This loop grabs all of the page specifications.
  687.  */
  688.        pagesperpage = 0 ;
  689.        while (*p != 0) {
  690.           if (pagesperpage >= MAXPPERP)
  691.          error("! too many page specifications") ;
  692.           if (*p == '-') {
  693.          reversed = 1 ;
  694.          p++ ;
  695.           } else
  696.          reversed = 0 ;
  697.           if (*p == 0 || *p == '(' || *p == ',')
  698.          pageno = 0 ;
  699.           else
  700.          pageno = myatol(&p) ;
  701.           if (*p == '(') {
  702.          p++ ;
  703.          hoffset = myatodim(&p) ;
  704.          if (*p++ != ',')
  705.             usage() ;
  706.          voffset = myatodim(&p) ;
  707.          if (*p++ != ')')
  708.             usage() ;
  709.           } else {
  710.          hoffset = 0 ;
  711.          voffset = 0 ;
  712.           }
  713.           pages[pagesperpage].hoffset = hoffset ;
  714.           pages[pagesperpage].voffset = voffset ;
  715.           pages[pagesperpage].pageno = pageno ;
  716.           pages[pagesperpage].reversed = reversed ;
  717.           pagesperpage++ ;
  718.           if (*p == ',')
  719.          p++ ;
  720.        } /* while */
  721.        break ;
  722. case 'n' :
  723.         if (*p == 0 && argv[i+1])
  724.            p = argv[++i] ;
  725. #ifdef SHORTINT
  726.         if (sscanf(p, "%ld", &maxpages)==0)
  727. #else    /* ~SHORTINT */
  728.         if (sscanf(p, "%d", &maxpages)==0)
  729. #endif    /* ~SHORTINT */
  730.            error("! Bad number of pages option (-n).") ;
  731.         break ;
  732. case 'q' : case 'Q' :
  733.         quiet = 0 ;
  734.         break ;
  735. case 'r' : case 'R' :
  736.         pages[0].reversed = 1;
  737.         break ;
  738.  
  739.  
  740. /*  Added 28.07.1993,    Jochen Wiedmann     */
  741. case 's' : case 'S' :
  742.         c = *p;
  743.         if (*(++p) == 0  &&  argv[i+1])
  744.           { p = argv[++i];
  745.           }
  746.         switch(c)
  747.           { case 'm' : case 'M' :
  748.             if (*p == 0)
  749.             error("Option -sm: Missing parameter?");
  750.             scale_magstep = atof(p);
  751.             break;
  752.         case 'w' : case 'W' :
  753.             if (*p == 0)
  754.             error("Option -sw: Missing parameter?");
  755.             scale_width = atof(p);
  756.             break;
  757.         case 'h' : case 'H' :
  758.             if (*p == 0)
  759.             error("Option -sh: Missing parameter?");
  760.             scale_height = atof(p);
  761.             break;
  762.         default :
  763.             error("Bad option: Not one of -sh, -sm, or -sw?");
  764.           }
  765.         break;
  766. /*                        */
  767.  
  768.  
  769. case 'x' :
  770.         if (*p == 0 && argv[i+1])
  771.            p = argv[++i] ;
  772.         while (*p != 0) {
  773.            if (*p == '(' && *(p+1) == '@' ) {
  774.           p+=2; exctransf[excludeseq][0] = myatol(&p); p++;
  775.           }
  776.            else if (*p == '@') {
  777.           p++; exctransf[excludeseq][0] = 1 ;
  778.           }
  779.            exclude[excludeseq][0]=myatol(&p);
  780.            if (*p == '.' && *(p+1) == '.' ) {
  781.           p += 2;
  782.           if (*p == '(' && *(p+1) == '@' ) {
  783.              p+=2; exctransf[excludeseq][1] = myatol(&p); p++;
  784.              }
  785.           else if (*p == '@') {
  786.              p++; exctransf[excludeseq][1] = 1 ;
  787.              }
  788.           exclude[excludeseq][1] = myatol(&p);
  789.            }
  790.            else {
  791.           exclude[excludeseq][1] = exclude[excludeseq][0];
  792.           exctransf[excludeseq][0] = exctransf[excludeseq][1] ;
  793.           }
  794.            excludeseq++ ;
  795.            if (*p != ',' && *p !=0 )
  796.           error("! Bad page range option (-x).") ;
  797.            if (*p == ',' )
  798.             p++ ;
  799.         } /* while */
  800.         break ;
  801. case '?' :
  802.         usage() ;
  803.         break ;
  804. default:
  805.         error("! Bad option, not one of filmnqrsx?") ;
  806.      }  /* switch c */
  807.       } else {    /* this a file name */
  808.      if (*iname == 0) { /* input file name */
  809.         register char *p ;
  810.  
  811.         lastext = 0 ;
  812.         iname = nextstring ;
  813.         p = argv[i] ;
  814.         while (*p) {
  815.            *nextstring = *p++ ;
  816.            if (*nextstring == '.')
  817.           lastext = nextstring - iname ;
  818.            else if (*nextstring == '/' || *nextstring == ':')
  819.           lastext = 0 ;
  820.            nextstring++ ;
  821.         }
  822.         if (lastext == 0) {
  823.            lastext = nextstring - iname ;
  824.            *nextstring++ = '.' ;
  825.            *nextstring++ = 'd' ;
  826.            *nextstring++ = 'v' ;
  827.            *nextstring++ = 'i' ;
  828.         }
  829.         *nextstring++ = 0 ;
  830.         if ((infile=fopen(iname, READBIN))==NULL)
  831.          error("! can't open input file") ;
  832.  
  833.      } else { /* output file name */
  834.         register char *p ;
  835.  
  836.         lastext = 0 ;
  837.         oname = nextstring ;
  838.         p = argv[i] ;
  839.         while (*p) {
  840.            *nextstring = *p++ ;
  841.            if (*nextstring == '.')
  842.           lastext = nextstring - oname ;
  843.            else if (*nextstring == '/' || *nextstring == ':')
  844.           lastext = 0 ;
  845.            nextstring++ ;
  846.         }
  847.         if (lastext == 0) {
  848.            lastext = nextstring - oname ;
  849.            *nextstring++ = '.' ;
  850.            *nextstring++ = 'd' ;
  851.            *nextstring++ = 'v' ;
  852.            *nextstring++ = 'i' ;
  853.         }
  854.         *nextstring++ = 0 ;
  855.        if (freopen(oname, WRITEBIN, stdout)==NULL)
  856.         error("! can't open output file") ;
  857.      }  /* end output file name */
  858.       } /* else argument with '-' */
  859.    }  /* for */
  860.    if (*iname == 0) {
  861.        (void)fprintf(stderr, banner) ;
  862.        error("! no input file specified");
  863.    }
  864.    if (*oname != 0 && !quiet) {
  865.        (void)fprintf(stderr, banner) ;
  866.        (void)fprintf(stderr, "%s -> %s\n",iname,oname);
  867.        temp = nextstring ;
  868.    }
  869. }
  870. /*
  871.  *   Grabs a pointer, and checks it for validity.
  872.  */
  873. integer ptr(where)
  874. register integer where ;
  875. {
  876.    fseek(infile,where,SEEK_SET);
  877.    where = signedquad() ;
  878.    if (where < -1L || where > inlength)
  879.       error("! dvi file malformed; impossible pointer") ;
  880.    return(where) ;
  881. }
  882.  
  883. /*
  884.  *   This routine store the page locations by tracing the pointers backwards.
  885.  */
  886. void searchpageloc()
  887. {
  888.    integer p,num ;
  889.  
  890.    num=pagecount-1;
  891.    for (p = ptr(postloc+1); num > 0; num--) {
  892.       if (dvibuf(p) != 139)
  893.      error("! missed a bop somehow") ;
  894.       else {
  895.      pageloc[num]=p;
  896.      pagenumbers[num]=signedquad();
  897.      }
  898.       p = ptr(p+41) ;
  899.    }
  900.    pageloc[num]=p;
  901.    (void)dvibuf(p);
  902.    pagenumbers[num]=signedquad();
  903. }
  904. /*
  905.  *   This routine simply reads the entire dvi file, and then initializes
  906.  *   some values about it.
  907.  */
  908. readdvifile() {
  909.    integer p ;
  910.    unsigned char c,d,e ;
  911.  
  912.    fseek(infile, 0L, 2) ;
  913.    inlength = ftell(infile) ;
  914.    if (inlength < 10)
  915.       error("! dvi file too short") ;
  916.    fseek(infile,-3L,SEEK_CUR);
  917.    for (p=inlength - 3; p > 0; p--) {
  918.       c = dvibyte (); d = dvibyte (); e = dvibyte ();
  919.       if (c == 2 && d == 0xdf /* dave fuchs */ &&
  920.                 e == 0xdf)
  921.      break ;
  922.       fseek(infile,-4L,SEEK_CUR);
  923.       }
  924.    if (p < 10)
  925.       error("! rather short dvi file, ain't it?") ;
  926.    postloc = ptr(p-4) ;
  927.    fseek(infile,postloc+5L,SEEK_SET);
  928.    if (signedquad() != 25400000 ||
  929.     signedquad() != 473628672)
  930.       error("! change this program to support non-TeX num/den values") ;
  931.    mag = signedquad() ;
  932.    if (mag < 1 || mag > 1000000)
  933.       error("! impossible magnification value") ;
  934.    fseek(infile,postloc+27L,SEEK_SET);
  935.    pagecount = twobytes() ;
  936.    if (pagecount < 1 || pagecount > 1000000)
  937.       error("! impossible page count value") ;
  938. /*
  939.  *   That's enough error checking; we probably have a correct dvi file.
  940.  *   Let's convert all the values we got from the command line into
  941.  *   units that we can actually use in the dvi file.
  942.  */
  943.    for (p=0; p<pagesperpage; p++) {
  944.       scalemag(&(pages[p].hoffset)) ;
  945.       scalemag(&(pages[p].voffset)) ;
  946.    }
  947. /*
  948.  *   Now let's grab us some font pointers.
  949.  */
  950.    pageloc = (integer *) calloc (pagecount, sizeof (integer));
  951.    if (pageloc == NULL)
  952.       error("!  Not enough memory for allocation of page pointers");
  953.    pagenumbers = (integer *) calloc (pagecount, sizeof (integer));
  954.    if (pagenumbers == NULL)
  955.       error("! Not enough memory for allocation of page numbers array");
  956.    searchpageloc();
  957.    transformpages();
  958.    free(pagenumbers);
  959.    p = postloc + 29 ;
  960.    while (1) {
  961.       c=dvibuf(p);
  962.       if (c == 249)
  963.      break ;
  964.       if (c == 138)
  965.      p++ ;
  966.       else if (c == 243) {
  967.      TeXfonts[dvibyte()] = p ;
  968.      p += fontdeflen(p) ;
  969.       } else
  970.      error("! only nop's and font def's allowed in postamble") ;
  971.    }
  972. /*
  973.  *   Now we check for a landscape special.  It should be the
  974.  *   *first* thing in the page that is at all complicated.
  975.  */
  976.  
  977.    p = pageloc[0L] + 45 ;
  978.    c=dvibuf(p);
  979.    while (comlen[c]) {
  980.       p += comlen[c] ;
  981.       c = dvibuf(p);
  982.    }
  983.    if (c == 239) {
  984.       stringdvibuf(p+2L,9L);
  985.       if (strncmp(temp, "landscape", 9)==0) {
  986.     landscape = p ;
  987.     rem0special = 1 ;
  988.       }
  989.    }
  990. }
  991. /*
  992.  *   Output a single byte, keeping track of where we are.
  993.  */
  994. outdvibyte(c)
  995. unsigned char c ;
  996. {
  997.    fputc(c, stdout) ;
  998.    dviloc++ ;
  999. }
  1000. /*
  1001.  *   Send out two bytes.
  1002.  */
  1003. outdvi2(v)
  1004. integer v ;
  1005. {
  1006.    outdvibyte((unsigned char)(v >> 8)) ;
  1007.    outdvibyte((unsigned char)(v & 255)) ;
  1008. }
  1009. /*
  1010.  *   Send out a longword.
  1011.  */
  1012. outdviquad(v)
  1013. integer v ;
  1014. {
  1015.    outdvi2(v >> 16) ;
  1016.    outdvi2(v & 65535) ;
  1017. }
  1018. /*
  1019.  *   This routine just copies some stuff from the buffer on out.
  1020.  *   Suppose the file is positioned correctly before
  1021.  */
  1022. putbuf(length)
  1023. integer length ;
  1024. {
  1025.    while ( length-- > 0 )
  1026.       outdvibyte(dvibyte()) ;
  1027. }
  1028. /*
  1029.  *   This routine outputs a string, terminated by null.
  1030.  */
  1031. putstr(s)
  1032. register unsigned char *s ;
  1033. {
  1034.    while (*s)
  1035.       outdvibyte(*s++) ;
  1036. }
  1037. /*
  1038.  *   Here we write the preamble to the dvi file.
  1039.  */
  1040. writepreamble() {
  1041.    longword mag;
  1042.  
  1043. /*   just copy the first 14 bytes of the file */
  1044.    fseek(infile,0L,SEEK_SET);
  1045.  
  1046.  
  1047. /*  Modified and added 28.07.1993,  Jochen Wiedmann    */
  1048. /*  Was: putbuf(14L) ;                                  */
  1049.    putbuf(10L); /*  Don't change DVI format, NUMerator and DENominator  */
  1050.    mag = fourbytes() *                  /*  Scale the magnification     */
  1051.      pow((double)1.2,scale_magstep);
  1052.    outdviquad(mag);
  1053. /*                            */
  1054.  
  1055.  
  1056. /*   and put our identifier. */
  1057.    putstr("\015dvidvi output") ;
  1058. }
  1059. /*
  1060.  *   This routine writes out a font definition.
  1061.  */
  1062. putfontdef(f)
  1063. int f ;
  1064. {
  1065.    integer p,q ;
  1066.  
  1067.    p = TeXfonts[f] ;
  1068.    q=fontdeflen(p) ;
  1069.    fseek(infile,p,SEEK_SET);
  1070.    putbuf(q) ;
  1071. }
  1072. /*
  1073.  *   The postamble is next.
  1074.  */
  1075. writepostamble() {
  1076.    int i ;
  1077.    integer p ;
  1078.    longword mag, height, width;
  1079.  
  1080.    p = dviloc ;
  1081.    outdvibyte(248) ;
  1082.    outdviquad(prevpp) ;
  1083.    fseek(infile,postloc+5,SEEK_SET);
  1084.  
  1085.  
  1086. /*  Modified and added    28.07.1993,    Jochen Wiedmann     */
  1087. /*  was: putbuf(20L) ;                                      */
  1088.    putbuf(8L);  /*  Don't change NUMerator and DENominator  */
  1089.  
  1090.    mag = fourbytes() * pow(1.2,scale_magstep);  /*  Scale magnification */
  1091.    outdviquad(mag);
  1092.    height = fourbytes() * pow(1.2,scale_height);/*  Scale height        */
  1093.    outdviquad(height);
  1094.    width = fourbytes() * pow(1.2,scale_width);  /*  Scale width         */
  1095.    outdviquad(width);
  1096. /*                                */
  1097.  
  1098.  
  1099.    outdvi2(twobytes()+1L) ; /* increase stack depth by 1 */
  1100.    outdvi2(outputpages) ;
  1101.    for (i=0; i<256; i++)
  1102.       if (fontseen[i])
  1103.      putfontdef(i) ;
  1104.    outdvibyte(249) ;
  1105.    outdviquad(p) ;
  1106.    outdvibyte(2) ;
  1107.    outdviquad(0xdfdfdfdfL) ;
  1108.    while (dviloc & 3)
  1109.       outdvibyte(0xdf) ;
  1110.    fclose(stdout) ;
  1111. }
  1112. /*
  1113.  *   This routine starts a page, by writing out a bop command.
  1114.  */
  1115. beginpage() {
  1116.    int i ;
  1117.    integer p ;
  1118.  
  1119.    p = dviloc ;
  1120.    outdvibyte(139) ;
  1121.    outdviquad(outputpages+1) ;
  1122.    for (i=0; i<9; i++)
  1123.       outdviquad(0L) ;
  1124.    outdviquad(prevpp) ;
  1125.    prevpp = p ;
  1126. }
  1127. /*
  1128.  *   This routine sends out a page.  We need to handle the
  1129.  *   landscape special, though.
  1130.  */
  1131. dopage(num)
  1132. integer num ;
  1133. {
  1134.    register integer p ;
  1135.    register int len ;
  1136.    integer v, oldp ;
  1137.    unsigned char c;
  1138.  
  1139. /*
  1140.  *   We want to take the base 10 log of the number.  It's probably
  1141.  *   small, so we do it quick.
  1142.  */
  1143.    if (! quiet) {
  1144.       int t = num+1, i = 0 ;
  1145.       if (t < 0) {
  1146.      t = -t ;
  1147.      i++ ;
  1148.       }
  1149.       do {
  1150.      i++ ;
  1151.      t /= 10 ;
  1152.       } while (t > 0) ;
  1153.       if (i + prettycolumn > 76) {
  1154.      fprintf(stderr, "\n") ;
  1155.      prettycolumn = 0 ;
  1156.       }
  1157.       prettycolumn += i + 1 ;
  1158. #ifdef SHORTINT
  1159.       (void)fprintf(stderr, "[%ld", num+1) ;
  1160. #else  /* ~SHORTINT */
  1161.       (void)fprintf(stderr, "[%d", num+1) ;
  1162. #endif /* ~SHORTINT */
  1163.       (void)fflush(stderr) ;
  1164.    }
  1165.    p = pageloc[num] + 45 ;
  1166.    c=dvibuf(p);
  1167.    while (c != 140) {
  1168.       if ((len=comlen[c]) > 0) {    /* most commands are simple */
  1169.      outdvibyte(c);
  1170.      putbuf((long)len-1) ;
  1171.      p += len ;
  1172.       } else {     /* but there are a few we need to treat specially */
  1173.      len = c ;
  1174.      if (171 <= len && len <= 235) {
  1175.         p++ ;
  1176.         if (len == 235)
  1177.            { len = dvibyte (); p++ ;}
  1178.         else
  1179.            len -= 171 ;
  1180.         if (!fontseen[len]) {
  1181.            putfontdef(len) ;
  1182.            fontseen[len] = 1 ;
  1183.            fseek(infile,p,SEEK_SET);
  1184.         }
  1185.         if (len < 64)
  1186.            outdvibyte(171 + len) ;
  1187.         else {
  1188.            outdvibyte(235) ;
  1189.            outdvibyte(len) ;
  1190.         }
  1191.      } else {
  1192.         v = 0 ;
  1193.         oldp = p++ ;
  1194.         switch(len) {
  1195. case 242:      v = dvibyte() ; p++ ;  break ;
  1196. case 241:      v = (v << 8) + dvibyte() ; p++ ; break ;
  1197. case 240:      v = (v << 8) + dvibyte() ; p++ ; break ;
  1198. case 239:      v = (v << 8) + dvibyte() ; p++ ;
  1199. /*
  1200.  *   Remove a landscape special on page 0, if one is found.
  1201.  */           stringdvibuf(oldp + len - 327,9);
  1202.            if (num || ! rem0special ||
  1203.             strncmp(temp, "landscape", 9)) {
  1204.           fseek (infile,oldp,SEEK_SET);
  1205.           putbuf(v + len - 237) ;
  1206.           }
  1207.            p = oldp + v + len - 237 ;
  1208.            fseek(infile,p,SEEK_SET);
  1209.            break ;
  1210. case 243: case 244: case 245: case 246:
  1211.            p += len - 230 ;
  1212.            p += dvibuf(p) ;
  1213.            p += dvibyte() + 2 ;
  1214.            fseek(infile,p,SEEK_SET);
  1215.            break ;
  1216. default:       fprintf(stderr, "Bad dvi command was %d at %ld\n", len, p) ;
  1217.            error("! lost sync dvi in file lost dvi sync file in") ;
  1218.         }
  1219.      }
  1220.       }
  1221.       c=dvibyte();
  1222.    }
  1223.    if (! quiet) {
  1224.       (void)fprintf(stderr, "] ") ;
  1225.       (void)fflush(stderr) ;
  1226.       prettycolumn += 2 ;
  1227.    }
  1228. }
  1229. /*
  1230.  *   Here we end a page.  Simple enough.
  1231.  */
  1232. endpage() {
  1233.    outputpages++ ;
  1234.    outdvibyte(140) ;
  1235. }
  1236. /*
  1237.  *   This is our main routine for output, which runs through all the
  1238.  *   pages we need to output.
  1239.  */
  1240. writedvifile() {
  1241.    integer pagenum ;
  1242.    int ppp ;
  1243.    integer actualpageno ;
  1244.    struct pagespec *ps ;
  1245.    Boolean beginp ;
  1246.  
  1247.    writepreamble() ;
  1248.    pagefake = (pagecount + modulo - 1) / modulo * modulo ;
  1249.    if ( maxpages < pagefake ) pagefake = maxpages;
  1250.    for (pagenum = 0; pagenum < pagefake; pagenum += modulo) {
  1251.       beginp = 1 ;
  1252.       for (ppp = 0, ps=pages; ppp < pagesperpage; ppp++, ps++) {
  1253.      if (ps->reversed)
  1254.         actualpageno = pagefake - pagenum - modulo + ps->pageno ;
  1255.      else
  1256.         actualpageno = pagenum + ps->pageno ;
  1257.      if (actualpageno < pagecount && selectedpage(actualpageno+1) ) {
  1258.         if (beginp) {
  1259.         beginpage() ;
  1260.         beginp = 0 ;
  1261.         }
  1262.         if (landscape) {
  1263.         fseek(infile,landscape,SEEK_SET);
  1264.         putbuf(dvibuf(landscape+1)+2L) ;
  1265.         landscape = 0 ;
  1266.         }
  1267.         if (pagesperpage)
  1268.         outdvibyte(141) ;
  1269.         if (ps->hoffset) {
  1270.         outdvibyte(146) ;
  1271.         outdviquad(ps->hoffset) ;
  1272.         }
  1273.         if (ps->voffset) {
  1274.         outdvibyte(160) ;
  1275.         outdviquad(ps->voffset) ;
  1276.         }
  1277.         dopage(actualpageno) ;
  1278.         if (pagesperpage)
  1279.         outdvibyte(142) ;
  1280.      }
  1281.       }
  1282.       if (beginp != 1) endpage() ;
  1283.    }
  1284.    writepostamble() ;
  1285. }
  1286. main(argc, argv)
  1287. int argc ;
  1288. char *argv[] ;
  1289. {
  1290.    processargs(argc, argv) ;
  1291.    readdvifile() ;
  1292.    writedvifile() ;
  1293. }
  1294.  
  1295.